using System;
using TestCases.CompareAssert.Core.Interfaces;

namespace TestCases.CompareAssert.Matchers
{
    public class ContextObjectMatcher<TFieldType>: IObjectMatcher<ICompareContext> where TFieldType: class
    {
        private readonly Func<IComparerObject, TFieldType> _fieldSelector;
        private readonly IObjectMatcher<TFieldType> _fieldMatcher;

        public ContextObjectMatcher(Func<IComparerObject, TFieldType> fieldSelector, IObjectMatcher<TFieldType> fieldMatcher)
        {
            _fieldSelector = fieldSelector;
            _fieldMatcher = fieldMatcher;
        }

        private bool IsObjectMatch(IComparerObject obj)
        {
            var field = _fieldSelector(obj);
            return field != null && _fieldMatcher.IsMatch(field);
        }

        public bool IsMatch(ICompareContext context)
        {
            return IsObjectMatch(context.Left) || IsObjectMatch(context.Right);
        }

        public bool Equals(ContextObjectMatcher<TFieldType> other)
        {
            return other != null && (other == this || _fieldMatcher.Equals(other._fieldMatcher));
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as ContextObjectMatcher<TFieldType>);
        }

        public override int GetHashCode()
        {
            return _fieldMatcher.GetHashCode();
        }
    }
}